import json
import re
import time

from django.conf import global_settings
from django.conf.global_settings import SESSION_COOKIE_AGE
from django.http import HttpResponse, JsonResponse, HttpResponseForbidden
from django.shortcuts import render, redirect
from django.contrib.auth import login, authenticate, logout, mixins
# Create your views here.
from django.utils.decorators import method_decorator

from django.views import View
from django_redis import get_redis_connection

from celery_task.email.tasks import celery_send_emails
from contents.models import SKU
from meiduo_mall.utils.response_code import RETCODE
from users.models import User
from django.contrib.auth.decorators import login_required
from .utils import get_encryped_url,check_url
from .models import Address
from carts.utils import merge_carts

class Register(View):
    '''注册页面'''
    def get(self,request):
        return render(request,'register.html')

    def post(self,request):
        # 1 获取请求数据
        request_dic = request.POST
        username = request_dic.get('username')
        password = request_dic.get('password')
        password2 = request_dic.get('password2')
        mobile = request_dic.get('mobile')
        allow = request_dic.get('allow')  #  两个值要么on,要么none
        client_sms_code = request_dic.get('sms_code')

        # 2 校验请求数据
        # all() ,如果有(),[],{},none返回False
        if not all([username,password,mobile,allow,client_sms_code]):
            return HttpResponse("缺少参数")
        if not re.match('^[a-zA-Z0-9_-]{5,20}$',username):
            return HttpResponse("用户名错误")
        if not re.match('^[a-zA-Z0-9]{8,20}',password):
            return HttpResponse('密码错误')
        if password != password2:
            return HttpResponse("密码不一致")
        if not re.match('1[345789]\d{9}',mobile):
            return HttpResponse('电话号码不对')
        conn_redis = get_redis_connection('verify')
        server_sms_code = conn_redis.get('sms_%s' % mobile)

        if server_sms_code == None:
            return render(request,'register.html',{'sms_code_errmsg':'短信验证码无效'})
        if server_sms_code.decode() != client_sms_code:
            return render(request,'register.html',{'sms_code_errmsg':'短信验证码有误'})

        user = User.objects.create_user(username=username,password=password,mobile=mobile)
        login(request, user)

        return redirect('/')




class UsernameCount(View):
    ''' 检查用户名是否重复 '''
    def get(self,request,username):
        count = User.objects.filter(username=username).count()
        content = {'count':count,'code':RETCODE.OK,'errmsg':'OK'}
        return JsonResponse(content)


class MobileCount(View):
    '''检查手机是否重复'''
    def get(self,request,mobile):
        count = User.objects.filter(mobile=mobile).count()
        content = {'count':count,'code':RETCODE.OK,'errmasg':'OK'}
        return JsonResponse(content)

class LoginView(View):
    # 登陆页面
    def get(self,request):
        return render(request,'login.html')
    def post(self,request):
        query_dict = request.POST
        username = query_dict.get('username')
        password = query_dict.get('password')
        is_remember = query_dict.get('remembered')

        # if re.match(r'1[345789]\d{9}',username):
        #     user = authenticate(request,mobile=username,password=password )
        # else:
        user = authenticate(request,username=username,password=password)
        if not user:
            return render(request,'login.html',{'account_errmsg':'用户名或密码错误'})
        # 保持用户登陆状态
        login(request,user)
        # 根据前端vue的获取cookies中的username的方案，设置cookies值传给前端
        next = request.GET.get('next')
        if next:
            response = redirect(next)
        else:
            response = redirect('/')
        response.set_cookie('username', username,max_age=SESSION_COOKIE_AGE if is_remember else None)

        # 合并购物车，注意得放在状态保持之后，否则request.user将是一个匿名用户
        merge_carts(request,response)

        if not is_remember:
            request.session.set_expiry(0)
            # session指定为none时，即默认为两周，当指定为0时候，则表示关闭浏览器则删除
            # cookie指定为none时，即关闭浏览器即删除，指定为0时候，表示为出生即死
        return response


class LogoutView(View):
    '''退出登陆'''
    def get(self,request):
        # 清除sessions
        logout(request)

        response = redirect('/login/')
        # 删除cookie
        response.delete_cookie('username')

        # 注意此处若login前面不加‘/’，则表示在当前路由下加上login的后缀
        return response

@method_decorator(login_required,name='get')
class InfoView(View):

    # def get(self,request):
    #
    #     if request.user.is_authenticated():
    #         # 注意is_authenticated后面有个d
    #         return render(request,'user_center_info.html')
    #     else:
    #         return redirect('/login/?next=info')

    def get(self,request):
        return render(request, 'user_center_info.html')

class EmailVerify(mixins.LoginRequiredMixin,View):
    '''获取邮箱'''
    def put(self,request):
        content = request.body
        content_dict = json.loads(content)
        email = content_dict.get('email')
        if not re.match(r'[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}',email):
            return JsonResponse({'code':RETCODE.EMAILERR,'errmsg':'邮箱错误'})
        user = request.user
        user.email = email
        user.save()
        verify_url = get_encryped_url(user)
        celery_send_emails.delay(email,verify_url)
        return JsonResponse({'code':RETCODE.OK,'errmsg':'保存成功'})

class EmailGet(mixins.LoginRequiredMixin,View):
    '''邮箱验证'''
    def get(self,request):
        token = request.GET.get('token')
        id,email = check_url(token)
        try:
            user = User.objects.get(id = id,email=email)
        except User.DoesNotExist:   # 注意此处的User
            return HttpResponse('找不到邮箱')
        else:
            user.email_active = True
            user.save()
            return redirect('/info/')


class AddressCreate(mixins.LoginRequiredMixin,View):
    '''新增收获地址'''
    def post(self,request):
        # 注意此处因为是逻辑删除，所以查找地址的时候得把逻辑删除的排除在外
        count = Address.objects.filter(user=request.user,is_deleted=False).count()
        if count > 20:
            return JsonResponse({'code':RETCODE.STOCKERR,'errmsg':'收获地址已经超过20个'})
        # python3.6以上不需要decode
        json_dict = json.loads(request.body)
        title = json_dict.get('title')
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')
        if not all([receiver,province_id,city_id,district_id,place,mobile]):
            return HttpResponseForbidden("缺少必传参数")
        if not re.match(r'1[345789]\d{9}',mobile):
            return JsonResponse({'code':RETCODE.MOBILEERR,'errmsg':'电话号码错误'})
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$',tel):
                return JsonResponse({'code':RETCODE.TELERR,'errmsg':'固定电话错误'})
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$',email):
                return JsonResponse({'code':RETCODE.EMAILERR,'errmsg':'邮箱错误'})
        address_model = Address.objects.create(
            # 注意按照字段来建对象
            user=request.user,
            title=title,
            receiver=receiver,
            province_id=province_id,
            city_id=city_id,
            district_id=district_id,
            place=place,
            mobile =mobile,
            tel=tel,
            email=email
        )
        address = request.user.default_address
        if address:
            if address.is_deleted:
                request.user.default_address_id = address_model.id
        else:
            request.user.default_address_id = address_model.id
        request.user.save()
        # 注意，此处的qs要取里面的值需要遍历
        # address_model = Address.objects.filter(user=request.user)
        data = {
            # 'user':request.user,
            'id':address_model.id,
            'title': title,
            'receiver': receiver,
            'province_id': province_id,
            'province':address_model.province.name,
            'city_id': city_id,
            'city':address_model.city.name,
            'district_id': district_id,
            'district': address_model.district.name,
            'place': place,
            'mobile': mobile,
            'tel': tel,
            'email': email,
        }
        return JsonResponse({'code':RETCODE.OK,'errmsg':'ok','address':data})

class DefaultAddress(mixins.LoginRequiredMixin,View):
    '''设置默认收获地址'''
    def put(self,request,id):
        try:
            address = Address.objects.get(id =id)
        except:
            return HttpResponseForbidden('地址id不存在')
        request.user.default_address_id = id
        request.user.save()
        return JsonResponse({'code':RETCODE.OK,'errmsg':'设置成功'})

class ChangeAddress(mixins.LoginRequiredMixin,View):
    '''修改地址'''
    def put(self,request,id):
        json_dict = json.loads(request.body)
        # 注意此处不能写成json_dict.title，这是错误写法，只有在模型类的对象中才有这种写法
        title = json_dict.get('title')
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')
        if not all([receiver,province_id,city_id,district_id,place,mobile]):
            return HttpResponseForbidden('缺少必传参数')
        if not re.match(r'1[345789]\d{9}',mobile):
            return JsonResponse({'code':RETCODE.MOBILEERR,'errmsg':'手机号码错误'})
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$',email):
                return JsonResponse({'code':RETCODE.EMAILERR,'errmsg':'邮箱错误'})
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$',tel):
                return JsonResponse({'code':RETCODE.TELERR,'errmsg':'固话错误'})
        # 查询要修改的模型类对象，注意is_deleted作为条件
        try:
            address_dict = Address.objects.get(id=id,user=request.user)
        except Address.DoesNotExist:
            return JsonResponse({'code':RETCODE.DBERR,'errmsg':'非法请求'})
        # 注意此处可以用fiter().update()修改值，但是这个无法更新修改时间
        address_dict.title = title
        address_dict.receiver = receiver
        address_dict.province_id = province_id
        address_dict.city_id = city_id
        address_dict.district_id = district_id
        address_dict.place = place
        address_dict.mobile = mobile
        address_dict.tel = tel
        address_dict.email = email
        address_dict.save()
        data = {
            'id':id,
            'title':title,
            'receiver' : receiver,
            'province_id':province_id,
            'city_id':city_id,
            'district_id':district_id,
            'place':place,
            'mobile':mobile,
            'tel':tel,
            'email':email,
        }
        return JsonResponse({'code':RETCODE.OK,'errmsg':'OK','address':data})

    def delete(self,request,id):
        try:
            address_model = Address.objects.get(id=id)
        except Address.DoesNotExist:
            return JsonResponse({'code':RETCODE.DBERR,'errmsg':'数据错误'})
        address_model.is_deleted = True
        address_model.save()
        return JsonResponse({'code':RETCODE.OK,'errmsg':'OK'})

class ChangeTitle(mixins.LoginRequiredMixin,View):
    '''修改地址标题头'''
    def put(self,request,id):
        try:
            address_model = Address.objects.get(id=id)
        except Address.DoesNotExist:
            return JsonResponse({'code':RETCODE.DBERR,'errmsg':'数据错误'})
        json_dict = json.loads(request.body)
        title = json_dict.get('title')
        address_model.title = title
        address_model.save()
        return JsonResponse({'code':RETCODE.OK,'errmsg':'OK'})

class ChangePassword(mixins.LoginRequiredMixin,View):
    '''修改用户密码'''
    def get(self,request):
        return render(request,'user_center_pass.html')
    def post(self,request):
        ''' 因为是密码等隐私的数据，所以用请求体表单的形式传递'''
        old_pwd = request.POST.get('old_pwd')
        new_pwd = request.POST.get('new_pwd')
        new_cpwd = request.POST.get('new_cpwd')
        if not all([old_pwd,new_pwd,new_cpwd]):
            return HttpResponseForbidden('缺少必传参数')
        if not request.user.check_password(old_pwd):
            return render(request,'user_center_pass.html',{'origin_pwd_errmsg':'用户名或密码错误'})
        if not re.match(r'[0-9A-Za-z]{8,20}',new_pwd):
            return HttpResponseForbidden('邮箱格式不正确')
        if new_cpwd != new_pwd:
            return HttpResponseForbidden('密码不一致')
        # 注意set_password已经把新秘密加密并赋值给模型对象了
        request.user.set_password(new_pwd)
        request.user.save()
        logout(request)
        response = redirect('/login/')
        response.delete_cookie('request.user')

        return response

class UserHistories(View):
    '''用户浏览记录'''
    def post(self,request):
        json_dirt = json.loads(request.body)    # 注意是用loads
        sku_id = json_dirt.get('sku_id')
        try:
            sku = SKU.objects.get(id = sku_id)
        except SKU.DoesNotExist:
            return HttpResponseForbidden('sku_id不存在')

        redis_conn = get_redis_connection('history')
        # # 去重
        # redis_conn.lrem('history%s' % request.user,0,sku_id)
        # # 保存
        # redis_conn.lpush('history%s' % request.user,sku_id)
        # # 截取前5个
        # redis_conn.ltrim('history%s' % request.user,0,4)


        # 用管道优化
        pl = redis_conn.pipeline()
        # 去重
        pl.lrem('history%s'%request.user,0,sku_id)
        # 插入
        pl.lpush('history%s'%request.user,sku_id)
        # 对列表切片，取出前5个历史记录
        pl.ltrim('history%s'% request.user,0,4)
        pl.execute()

        return JsonResponse({'code':RETCODE.OK,'errmsg':'OK'})

    def get(self,request):
        if not request.user.is_authenticated:
            return HttpResponseForbidden('非法请求')
        redis_conn = get_redis_connection('history')
        sku_redis = redis_conn.lrange('history%s'% request.user,0,-1)
        sku_list = []
        for sku_id in sku_redis:
            sku_model = SKU.objects.get(id = sku_id)
            sku_list.append({
                'default_image_url':sku_model.default_image.url,
                'id':sku_model.id,
                'name':sku_model.name,
                'price':sku_model.price
            })
        return JsonResponse({'code':RETCODE.OK,'errmsg':'OK','skus':sku_list})

